import React, { Component } from 'react';
import { Balloon, Tree, Badge, Button } from '@teamix/ui';
import sha1 from 'sha1';
import treeFromPaths from './path-to-tree';
import { ButtonIcon, YunxiaoIcon, Title } from '@alife/devops-ui';
import track from 'utils/track';
import { getFeature } from 'utils/features';
import ListEmpty from 'atComponents/ListEmpty';
import ListLoading from 'atComponents/ListLoading';
import { navigate, navigateOpen } from 'utils/router';
import FileIcon from 'components/fileIcon';
import FilePanel from 'components/filePanel';
import Highlighter from 'components/highlighter';
import intl from '../../locale';
import { getWebIdeUrl } from 'api';

export default class DiffTree extends Component {
  componentDidMount() {
    const header = document.querySelector('.mr-detail-content-header');
    const mrTabList = document.querySelector('.mr-tab-list');
    const top = document.querySelector('.mr-change-tree-top');
    const viewportHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
    const mrTabListHeight = mrTabList ? mrTabList.offsetHeight : 0;
    const headerHeight = header ? header.offsetHeight : 0;
    const topHeight = top ? top.offsetHeight : 0;
    const otherHeight = 51; // 91 顶部距离
    const $leftDom = document.querySelector('.changes-left');
    if ($leftDom) {
      $leftDom.style['max-height'] = `${`${
        viewportHeight - (mrTabListHeight + headerHeight + otherHeight + topHeight)
      }px`}`;
    }
  }

  componentWillUnmount() {
    if (document.querySelector('.mr-detail-content-body ')) {
      document.querySelector('.mr-detail-content-body ').classList.remove('hideScroll');
    }
  }

  renderIcon = (item, isMarkAsUnread) => {
    if (item.label.isFile) {
      const fileIcon = <FileIcon className="file-icon" fileName={item.label.name} />;

      if (isMarkAsUnread) {
        return <Badge dot>{fileIcon}</Badge>;
      } else {
        return fileIcon;
      }
    } else {
      return <YunxiaoIcon type={'folder-line'} className="file-icon" style={{ color: 'var(--gray-06, #8C8C8C)' }} />;
    }
  };

  loop = (data) =>
    data.map((item) => {
      const { diffs, codeReviewDetail, unreadFileObjectIds } = this.props;
      const { pathResource } = window.FORCE;
      const curPath = `/${pathResource.fullPath}/merge_request/${codeReviewDetail.id}`;
      const diffData = diffs.find((diff) => diff.new_path === item.label.path) || {};
      const selectKey = this.getSelectedKey();
      const isSelected = selectKey === `tree_${sha1(item.label.path)}`;
        let isMarkAsUnread;
        if (diffData.deleted_file) {
          isMarkAsUnread = diffData.new_object_id && unreadFileObjectIds.includes(diffData.old_object_id);
        } else {
          isMarkAsUnread = diffData.new_object_id && unreadFileObjectIds.includes(diffData.new_object_id);
        }
      let solvedNoteLength = 0;
      if (item.label.isFile && diffData.total_note) {
        solvedNoteLength = diffData.total_note - diffData.unresolved_note;
      }
      return (
        <Tree.Node
          label={
            <span
              key={`${sha1(item.label.path)}_label`}
              className={`label-content ${isSelected ? 'selected' : ''}`}
              onClick={(e) => {
                e.stopPropagation();
                if (item.label.isFile) {
                  track({
                    action: 'click_tree_file',
                    page: 'Repo-MR-changes',
                  });

                  if (window.location.pathname !== `${curPath}/changes`) {
                    navigate(`${curPath}/changes`);
                    this.props.changeMrTabKey('changes');
                  }
                  window.location.hash = `#file=${sha1(item.label.path)}`;
                  // 如果是单文件切换文件，滚动条滚动到顶部
                  if (this.props.forceCrFileViewType === 'single') {
                    document.querySelector('#mr-content-body').scrollTop = 0;
                  }
                }
              }}
            >
              {this.renderIcon(item, isMarkAsUnread)}{' '}
              <Title
                align="t"
                trigger={
                  <span className={diffData.read ? 'read' : 'unread'}>
                    {item.label.isFile ? item.label.name : item.label.name.slice(0, -1)}
                  </span>
                }
              >
                {item.label.isFile ? item.label.name : item.label.name.slice(0, -1)}
              </Title>
              {item.label.isFile && (
                <span className="label-content-right">
                  {diffData.total_note ? (
                    <Balloon.Tooltip
                      v2={false} // FIXME v2版本有bug，复现链接：https://codeup.aliyun.com/60d54f3daccf2bbd6659f3ad/Codeup-Demo/merge_request/3365863
                      trigger={
                        <span className="comment-status">
                          <ButtonIcon
                            name="message-line"
                            onClick={(e) => {
                              e.stopPropagation();
                              if (item.label.isFile && diffData.total_note > 0) {
                                // mr 评论优化 打开评论面板 。在单文件的时候，不需要文件滚动
                                this.props.commentJump(sha1(item.label.path));
                                this.props.openCommentPanel({
                                  isShowComment: true,
                                  curCommentStatus: 'open',
                                });
                              }
                            }}
                          />
                          {diffData.total_note - diffData.unresolved_note}/{diffData.total_note}
                        </span>
                      }
                      align="t"
                    >
                      {intl.get(
                        {
                          id: 'code-assets.components.diffTree.ATotalOfDiffdatatotalnoteComments',
                          defaultMessage:
                            '共 {diffDataTotalNote} 条评论, {solvedNoteLength} 条已解决',
                        },

                        {
                          diffDataTotalNote: diffData.total_note,
                          solvedNoteLength,
                        },
                      )}
                    </Balloon.Tooltip>
                  ) : null}
                  {diffData.add_lines ? (
                    <Balloon.Tooltip
                      v2={false}
                      trigger={
                        <span className="changes-tree-item-right-item add-lines">
                          + {diffData.add_lines}
                        </span>
                      }
                      align="t"
                    >
                      {intl.get(
                        {
                          id: 'code-assets.components.diffTree.AddedDiffdataaddlinesLines',
                          defaultMessage: '增加了 {diffDataAddLines} 行',
                        },

                        { diffDataAddLines: diffData.add_lines },
                      )}
                    </Balloon.Tooltip>
                  ) : null}
                  {diffData.del_lines ? (
                    <Balloon.Tooltip
                      v2={false}
                      trigger={
                        <span
                          className="changes-tree-item-right-item del-lines"
                          style={{ marginLeft: diffData.add_lines ? 8 : 0 }}
                        >
                          - {diffData.del_lines}
                        </span>
                      }
                      align="t"
                    >
                      {intl.get(
                        {
                          id: 'code-assets.components.diffTree.DiffdatadellinesLinesHaveBeenDeleted',
                          defaultMessage: '删除了 {diffDataDelLines} 行',
                        },

                        { diffDataDelLines: diffData.del_lines },
                      )}
                    </Balloon.Tooltip>
                  ) : null}
                </span>
              )}
            </span>
          }
          key={`tree_${sha1(item.label.path)}`}
          isLeaf={item.label.isFile}
        >
          {item.nodes && this.loop(item.nodes)}
        </Tree.Node>
      );
    });

  getSelectedKey = () => {
    // 滚动高亮的值 leftTreeSelectKey
    const { diffs, diffsSha1Map, hash, leftTreeSelectKey, mrTabKey } = this.props;
    const { file: activeFileSha } = hash;
    const activeFilePath = activeFileSha ? diffsSha1Map[activeFileSha] : diffs[0].new_path;
    let selectKey = '';
    // 不在changes，树无高亮
    if (mrTabKey !== 'changes') {
      return '';
    }
    if (leftTreeSelectKey) {
      selectKey = `tree_${leftTreeSelectKey}`;
    } else if (activeFilePath) {
      selectKey = `tree_${sha1(activeFilePath)}`;
    }
    return selectKey;
  };

  treeLoop(treeData) {
    if (!treeData.nodes.length) {
      return null;
    }

    const selectKey = this.getSelectedKey();
    // const virtualState = this.useVirtualHander(treeData?.nodes);
    return (
      <Tree
        defaultExpandAll
        selectedKeys={[selectKey]}
        className="file-tree"
        mode="directory"
        isLabelBlock
        animation={false}
      >
        {this.loop(treeData.nodes)}
      </Tree>
    );
  }

  useVirtualHander = (data) => {
    if (!data) return false;
    let num = 0;
    const numstate = (array) => {
      for (let index = 0; index < array.length; index++) {
        num += 1;
        if (Array.isArray(array[index]?.nodes) && array[index]?.nodes?.length > 0) {
          numstate(array[index].nodes);
        }
      }
    };
    numstate(data);
    return num;
  };

  goWebIde = () => {
    const { projectMergeRequestDetailRoot } = this.props;
    track({
      action: 'goto_webide',
      page: 'Repo-MR',
      type: '',
      control: '',
    });

    getWebIdeUrl(
      {
        filepath: '',
        branch: projectMergeRequestDetailRoot.source_branch,
        commit: '',
        line: '',
        column: '',
        type: 'mergerequest',
        merge_commit: projectMergeRequestDetailRoot.target_branch,
        mergerequestId: projectMergeRequestDetailRoot.id,
      },
      projectMergeRequestDetailRoot.project_id,
    )
      .then((result) => {
        navigateOpen(result.endpoint);
      })
      .catch((err) => {
        console.error(err);
      });
  };

  getTreeFailReasonRender = (title) => {
    return (
      <div style={{ padding: '0 16px', fontSize: 12, color: '#a6a6a6', textAlign: 'center' }}>
        {title}
      </div>
    );
  };

  getDescriptionHander = (data) => {
    const { project_clone_download, ipSetting } = this.props;
    if (!getFeature('WebIDE.entrance.mr')) return '';
    if (ipSetting && ipSetting.ip_whitelist_enabled && ipSetting.scope === 'all') {
      return (
        <Balloon.Tooltip
          align="l"
          trigger={
            <Button disabled onClick={() => this.goWebIde()}>
              {intl.get({
                id: 'code-assets.components.diffTree.OpenWeifeng',
                defaultMessage: '打开 WebIDE',
              })}
            </Button>
          }
        >
          {intl.get({
            id: 'code-assets.components.mergeRequsetInfo.TheEnterpriseHasEnabledIp',
            defaultMessage: '企业已启用 IP 白名单严格管控，暂不支持使用 WebIDE',
          })}
        </Balloon.Tooltip>
      );
    } else if (
      project_clone_download?.httpCloneLimit?.state === 'disable' &&
      project_clone_download?.sshCloneLimit?.state === 'disable'
    ) {
      return (
        <Balloon.Tooltip
          align="t"
          trigger={
            <Button disabled onClick={() => this.goWebIde()}>
              {intl.get({
                id: 'code-assets.components.diffTree.OpenWeifeng',
                defaultMessage: '打开 WebIDE',
              })}
            </Button>
          }
        >
          已启用仓库克隆下载控制，暂不支持使用 WebIDE，请联系管理员处理
        </Balloon.Tooltip>
      );
    } else if (data) {
      return (
        <Button onClick={() => this.goWebIde()}>
          {intl.get({
            id: 'code-assets.components.diffTree.OpenWeifeng',
            defaultMessage: '打开 WebIDE',
          })}
        </Button>
      );
    }
  };

  renderTree = (diffs, treeData, isCommitsAndDiffsLoading) => {
    if (diffs.length) {
      return <div>{this.treeLoop(treeData)}</div>;
    } else if (isCommitsAndDiffsLoading) {
      return <ListLoading />;
    } else {
      const { getTreeFailReason, getTreeFailError } = this.props;
      if (getTreeFailError && getTreeFailError.errorCode === 'MERGE_BASE_NOT_FOUND_ERROR') {
        return (
          <div className="mr-diffs-empty">
            <ListEmpty
              size="small"
              type="card"
              content="无效的合并请求"
              description={
                <div style={{ textAlign: 'left' }}>
                  <p>
                    评审提交与目标分支无关联提交，可能因为修改了目标分支的历史提交导致失去关联。
                  </p>
                  <div>
                    如需重新关联，请在本地获取目标分支最新内容，执行变基（rebase）重新建立与目标分支的关联；如需合并两个无关分支，请在本地执行：
                  </div>
                  <div>
                    <FilePanel.Body>
                      <div>
                        <Highlighter
                          // language={`${fileName.split('.')[fileName.split('.').length - 1]}`}
                          // 缺陷https://work.aone.alibaba-inc.com/issue/30017264，先简单修复vue文件style识别内容丢失问题
                          // 缺陷：https://work.aone.alibaba-inc.com/issue/30620064， html内容丢失
                          language={''}
                          showLineNumbers={false}
                          wrapLines
                        >
                          {'git merge  --allow-unrelated-histories <BRANCH>'}
                        </Highlighter>
                      </div>
                    </FilePanel.Body>
                  </div>
                </div>
              }
              image="none"
              className="no-content no-btns"
            />
          </div>
        );
      }
      return (
        <div className="mr-diffs-empty">
          <ListEmpty
            size="small"
            type="card"
            content={
              getTreeFailReason
                ? this.getTreeFailReasonRender(getTreeFailReason)
                : intl.get({
                    id: 'code-assets.components.diffTree.NoFileChanges',
                    defaultMessage: '没有文件改动',
                  })
            }
            description={this.getDescriptionHander(getTreeFailReason)}
            image="none"
            className="no-content no-btns"
          />
        </div>
      );
    }
  };

  render() {
    const { diffs, isCommitsAndDiffsLoading } = this.props;

    const treeData = treeFromPaths(
      diffs.map((item) => item.new_path),
      '',
      (parent, file, explicit) => ({
        path: `${parent}${file}`,
        name: `${file}`,
        isFile: explicit,
      }),
    );

    const recursiveFuncNode = (node) => {
      if (
        node.label &&
        !node.label.isFile &&
        node.nodes.length === 1 &&
        !node.nodes[0].label.isFile
      ) {
        node.label = {
          path: node.nodes[0].label.path,
          name: node.label.name + node.nodes[0].label.name,
          isFile: node.nodes[0].label.isFile,
        };

        node.nodes = node.nodes[0].nodes;

        recursiveFuncNode(node);
      } else if (node.nodes.length) {
        node.nodes.forEach((item) => {
          recursiveFuncNode(item);
        });
      }
    };

    if (treeData.nodes.length) {
      treeData.nodes.forEach((node) => {
        recursiveFuncNode(node);
      });
    }

    return (
      <div className="changes-left-section">
        <div className="changes-tree">
          {this.renderTree(diffs, treeData, isCommitsAndDiffsLoading)}
        </div>
      </div>
    );
  }
}
